/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javanlp;

/**
 * @author davidcummings
 */
public class FeatureExtractor {
    
    final static String vwpTags[] = {"NN","NNS","NNP","NNPS","IN","JJ","JJR",
        "JJS","DT","PRP","PRP$","TO"}; 
    // can only occur in VW*P relations, not V only
    final static String whTags[] = {"WDT","WP","WP$","WRB"};
    final static String npTags[] = {"NN","NNS","NNP","NNPS"};
    final static String prepTags[] = {"IN"};
    final static String ccTags[] = {"CC"};
    
    /**
     * @param tokens One sentence, tokenized into words
     * @param tags   POS tags for each token
     * @param x      Span representing NP to the left of the relation phrase
     * @param r      Span representing the relation phrase
     * @param y      Span representing NP to the right of the relation phrase
     * @return       boolean array of features   */
    public static boolean[] getFeatures(String tokens[], String tags[], 
            Spans x, Spans r, Spans y) {
        // initialize all features to false, except the first
        boolean features[] = new boolean[20];
        for (boolean feature : features) { feature = false;  }
        features[0] = true;
        // Features 1,2,3: length of sentence
        if (tokens.length <= 10) { features[1] = true;
        } else if (tokens.length <= 20) { features[2] = true;
        } else { features[3] = true; }
        
        // Feature 4: (x,r,y) covers all words in sentence
        if ((x.getLength() + r.getLength() + y.getLength()) == tokens.length){
            features[4] = true; }
        
        // Feature 5: s begins with x
        if ( x.getBegin() == 0 ) { features[5] = true; }
        // Features 6,7: x or y is a proper noun
        if ( isProperNoun(tags, x) ) { features[6] = true;   }
        if ( isProperNoun(tags, y) ) { features[7] = true;   }
        // Features 8,9,10,11,12: r ends with in, for, of, on, to
        String rEnd = tokens[r.getEnd()];
        if ( rEnd.equalsIgnoreCase("in") ) {  features[8] = true;
        } else if ( rEnd.equalsIgnoreCase("for") ) { features[9] = true; } 
        else if ( rEnd.equalsIgnoreCase("of") ) { features[10] = true;  } 
        else if ( rEnd.equalsIgnoreCase("on") ) { features[11] = true; } 
        else if ( rEnd.equalsIgnoreCase("to") ) { features[12] = true; }
        // Features 13,14: r matches V only, or VW*P
        if ( isSimpleVerb(tags, r) ) {  features[13] = true;  } 
        else {  features[14] = true;   }
        // Feature 15: WH-word to the left of r
        if ( findTag(tags, whTags, r.getBegin(), -1) ) {features[15] = true; }
        // Feature 16: NP to the left of x
        if ( findTag(tags, npTags, x.getBegin(), -1) ) { features[16] = true;}
        // Feature 17: NP to the right of y
        if ( findTag(tags, npTags, y.getEnd(), 1) ) { features[17] = true; }
        // Feature 18: preposition to the left of x
        if ( findTag(tags, prepTags, x.getBegin(), -1) ) {features[18] = true;}
        // Feature 19: CC to the left of r
        if ( findTag(tags, ccTags, r.getBegin(), -1) ) {features[19] = true;}
        return features;
    }
    
    // convenience method to wrap getFeatures and return doubles 1.0 or 0.0
    public static double[] getFeaturesDoubles(String tokens[], String tags[], 
            Spans x, Spans r, Spans y) {
        boolean in[] = getFeatures(tokens,tags,x,r,y);
        double out[] = new double[in.length];
        for (int i = 0; i < in.length; i++) {
            out[i] =  in[i] ? 1.0 : 0.0;
        }
        return out;
    }
    
    // all nouns are NNP or NNPS, not NN or NNS.
    private static boolean isProperNoun(String tags[], Spans x) {
        for (int i = x.getBegin(); i <= x.getEnd(); i++) {
            if ( tags[i].equals("NN") || tags[i].equals("NNS")  ) {
                return false; }   }
        return true;
    }
    
    // the relation phrase matches V, not VW*P
    private static boolean isSimpleVerb(String tags[], Spans r) {
        for (int i = r.getBegin()+1; i <= r.getEnd(); i++) {
            for (int j = 0; j < vwpTags.length; j++) {
                if (tags[i].equals(vwpTags[j])) {
                    return false;  }  }
        }
        return true;
    }
    
    // ignoring beginPoint, works through all tags looking for any 
    //tag matching one of the targets
    private static boolean findTag(String tags[], String targets[], 
            int beginPoint, int increment) {
        int i = beginPoint + increment;
        while (i > 0 && i < tags.length) {
            for (int j = 0; j < targets.length; j++) {
                if (tags[i].equals(targets[j])) {
                    return true;
                }
            }
            i += increment;
        }
        return false;
    }
}
